package com.gxa.community.sso.service.impl;

import com.aliyuncs.dysmsapi.model.v20170525.SendSmsResponse;
import com.aliyuncs.exceptions.ClientException;
import com.gxa.community.core.common.CommonVar;
import com.gxa.community.core.common.ResultMsg;
import com.gxa.community.core.utils.R;
import com.gxa.community.sso.entity.UserInfo;
import com.gxa.community.sso.entity.login.LoginVo;
import com.gxa.community.sso.repository.UserRepository;
import com.gxa.community.sso.service.LoginService;
import com.gxa.community.sso.utils.SendSms;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundValueOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;

import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * @author bill
 * @Transactional 处理持久层事务, 还能在redis操作完毕后关闭连接
 * @date 2022/7/6 11:18
 */
@Service
@Transactional(rollbackFor = Throwable.class)
public class LoginServiceImpl implements LoginService {
    @Autowired
    RedisTemplate<String, Object> redisTemplate;
    @Autowired
    UserRepository userRepository;

    /**
     * 用户登录
     * @param phone
     * @param code
     * @return
     */
    @Override
    public R login(String phone, String code) {
        String redisCode = (String) redisTemplate.opsForValue().get(CommonVar.PHONE_SEND_MSG_CODE.getKeyWord() + phone);
        //获取并判断手机验证码
        if (ObjectUtils.isEmpty(redisCode))
            return R.error(ResultMsg.SMS_PHONE_CODE_ERROR.getMsg());

        //删除redis手机验证码
        redisTemplate.delete(CommonVar.PHONE_SEND_MSG_CODE.getKeyWord() + phone);

        UserInfo s = userRepository.queryUserinfoByPhone(phone);

        UserInfo userInfo = null;

        //生成用户唯一id
        if (ObjectUtils.isEmpty(s)) {
            userInfo = new UserInfo();
            userInfo.setNickName(CommonVar.USER_DEFAULT_PREFIX_MARK.getKeyWord() + phone);
            userInfo.setStatus(1);
            //生成用户编号

        } else {
            userInfo = new UserInfo();
            userInfo = s;
        }
        userInfo.setPhone(phone);
        userInfo.setCreateTime(System.currentTimeMillis());

        if (userInfo.getStatus() != 1)
            return R.error(ResultMsg.LOGIN_ACCOUNT_INVALID.getMsg());

        //创建token 登录
        if (!ObjectUtils.isEmpty(userInfo.getToken()))
            redisTemplate.delete(CommonVar.USER_LOGIN_AXLAB_TOKEN.getKeyWord() + userInfo.getToken());

        String token = UUID.randomUUID().toString().replace("-", "");
        String key = CommonVar.USER_LOGIN_AXLAB_TOKEN.getKeyWord() + token;
        userInfo.setToken(token);

        UserInfo save = userRepository.save(userInfo);

        save.setToken(null);
        //如果是团长则存储团长信息
        LoginVo loginVo = userRepository.queryUserInfoByType(save.getUserId());

        if (!ObjectUtils.isEmpty(loginVo)){
            redisTemplate.opsForValue().set(CommonVar.AGENT_LOGIN_AXLAB_TOKEN.getKeyWord() + token, loginVo);
        }
        redisTemplate.opsForValue().set(key, save);
        return code.equals(redisCode) ? R.ok().put("token",token) : R.error();
    }
    /**
     * 获取短信
     * @param token
     * @param phone
     * @return
     * @throws ClientException
     */
    @Override
    public R sendSms(String token, String phone) throws ClientException {
        //判断此次请求是否真实
        String redisPhone = (String) redisTemplate.opsForValue().get(CommonVar.PHONE_SEND_MSG_TOKEN.getKeyWord() + token);

        if (ObjectUtils.isEmpty(redisPhone))
            return R.error(ResultMsg.SMS_PHONE_REQUEST_ERROR.getMsg());

        //sendMsg
        String msgCode = SendSms.getMsgCode();
        String codeTemplate = "{\"code\":" + msgCode + "}";
        SendSmsResponse response = SendSms.sendSms(phone, "SMS_204986028", codeTemplate);

        if (!"OK".equals(response.getCode()))
            return R.error(ResultMsg.SMS_PHONE_REQUEST_ERROR.getMsg());

        //保存code 用于登录验证
        redisTemplate.opsForValue().set(CommonVar.PHONE_SEND_MSG_CODE.getKeyWord() + phone, msgCode,5, TimeUnit.MINUTES);
        //发送成功进行发送限制-一分钟
        redisTemplate.opsForValue().set(CommonVar.PHONE_SEND_MSG_MARK.getKeyWord() + phone, phone, 1, TimeUnit.MINUTES);
        //发送成功进行发送限制-一删除token
        redisTemplate.delete(CommonVar.PHONE_SEND_MSG_TOKEN.getKeyWord() + token);

        return  R.ok(ResultMsg.SMS_PHONE_CODE_SEND_SUCCESS.getMsg());
    }

    /**
     * 获取短信真实接口，短信限制一个手机号一分钟
     * @param phone
     * @return
     */
    @Override
    public R getSendSmsInterface(String phone) {
        //生成发送信息token，用户请求真实发送短信接口。
        String[] split = UUID.randomUUID().toString().split("-");

        redisTemplate.opsForValue().set(CommonVar.PHONE_SEND_MSG_TOKEN.getKeyWord() + split[1], phone, 1, TimeUnit.MINUTES);

        redisTemplate.opsForValue().set(CommonVar.SEND_SMS_INTERFACE_GET.getKeyWord() + phone,phone,1,TimeUnit.MINUTES);
        //返回信息发送接口
        return R.ok().put("Url", "user/sendSms/" + split[1] + "/" + phone);
    }

    @Override
    public R checkWithToken(String token) {

        BoundValueOperations<String, Object> boundValueOps =
                redisTemplate.boundValueOps(CommonVar.USER_LOGIN_AXLAB_TOKEN.getKeyWord() + token);

        //判断redis中的key是否存在
        UserInfo o = (UserInfo) boundValueOps.get();
        if (ObjectUtils.isEmpty(o))
            R.error(ResultMsg.LOGIN_FAILURE.getMsg());

        boundValueOps.expire(30, TimeUnit.MINUTES);

        assert o != null;

        return R.ok("成功").put("data",o);
    }
}
